package com.cysyz.mylib.dao;


import java.util.LinkedHashMap;
import java.util.Map;

public class Conds {
	private String defaultTableAsName;
	private StringBuilder conditions = new StringBuilder(" where 1=1 ");
	private Map<String, Object> paramPlaceAndValues = new LinkedHashMap<String, Object>();
	private StringBuilder orderby = new StringBuilder("");
	
	public Conds () {}
	public Conds(String defaultTableAsName) {
		this.defaultTableAsName = defaultTableAsName;
	}

	public Conds addFilter(String tableName, String left, String operator, Object right) {
		this.addFilter0(tableName, AndOr.AND, left, operator, right);
		return this;
	}
	
	public Conds addFilterByDefaultTableName(String left, String operator, Object right) {
		this.addFilter0(null, AndOr.AND, left, operator, right);
		return this;
	}
	
	public Conds addFilter(String tableName, AndOr andOr, String left, Object right) {
		this.addFilter0(tableName, andOr, left, "=", right);
		return this;
	}
	
	/**
	 * 添加 and 及运算符为=的条件
	 * @param left
	 * @param right
	 */
	public Conds addFilter(String tableName, String left, Object right) {
		this.addFilter0(tableName, AndOr.AND, left, "=", right);
		return this;
	}
	
	public Conds addFilter(AndOr andOr, String left, Object right) {
		this.addFilter0(null, andOr, left, "=", right);
		return this;
	}
	
	public Conds addFilter(String left, Object right) {
		this.addFilter0(null, AndOr.AND, left, "=", right);
		return this;
	}
	
	public Conds addFilters(AndOr andOr, Conds conds) {
		appendStrBySpace(andOr.getValue());
		appendStrBySpace("(");
		appendStrBySpace(conds.toString());
		appendStrBySpace(")");
		return this;
	}
	
	public Conds addFilters(Conds conds) {
		addFilters(AndOr.AND, conds); 
		paramPlaceAndValues.putAll(conds.getParamPlaceAndValues());
		return this;
	}

	public Conds setOrderBy(String orderByColumn) {
		return this.setOrderBy(defaultTableAsName, orderByColumn, AscOrDesc.ASC);
	}
	
	public Conds setOrderBy(String tableName, String orderByColumn) {
		return this.setOrderBy(tableName, orderByColumn, AscOrDesc.ASC);
	}

	public Conds setOrderBy(String tableName, String orderByColumn, AscOrDesc ascOrDesc) {
		this.orderby.append(" order by ").append(tableName).append(".").append(orderByColumn).append(" ").append(ascOrDesc.value);
		return this;
	}
	
	/**
	 * 
	 * @param andOr And or 
	 * @param left 左侧
	 * @param operator 运算符
	 * @param right 右侧
	 */
	private void addFilter0(String tableName, AndOr andOr, String left, String operator, Object right) {
		if (andOr != null && left != null && operator != null && right != null) {
			appendStrBySpace(andOr.getValue());
			
			if (tableName == null) {
				tableName = defaultTableAsName;
			}
			
			if (operator.matches("\\s*%\\s*?like\\s*?%\\s*")) {
				operator = "like";
				right = "%" + right + "%";
			} else if (operator.matches("\\s*like\\s*?%\\s*|\\s*like\\s*")) {
				operator = "like";
				right = right + "%";
			} else if (operator.matches("\\s*%\\s*?like\\s*")) {
				operator = "like";
				right = "%" + right;
			}
			//以命名参数的方式生成条件
			String placeHolder = setNameedParameterAndValue(tableName, left, right);
			if (operator != null && operator.trim().equals("in")) {
				placeHolder = "(" +placeHolder+")";
			}
			addOneCond0(tableName, left, operator, placeHolder);
		}
	}

	private String setNameedParameterAndValue(String tableName, String left,
			Object right) {
		StringBuilder namedParameter = new StringBuilder();
		namedParameter.append(tableName);
		namedParameter.append(left.replaceAll("\\.", (int)(Math.random()*100)+""));
		if (paramPlaceAndValues.containsKey(namedParameter.toString())) {
			namedParameter.append(System.currentTimeMillis());
		}
		StringBuilder placeHolder = new StringBuilder();
		placeHolder.append(":");
		placeHolder.append(namedParameter);
		paramPlaceAndValues.put(namedParameter.toString(), right);
		return placeHolder.toString();
	}
	
	private void addOneCond0(String tableName, String left, String operator, String right) {
		if (tableName != null) {
			appendStrBySpace(tableName.toLowerCase());
			conditions.append(".");
		}
		conditions.append(left);
		appendStrBySpace(operator);
		appendStrBySpace(right);
	}
	
	private void appendStrBySpace(String left) {
		conditions.append(" ");
		conditions.append(left);
		conditions.append(" ");
		
	}
	
	
	public Map<String, Object> getParamPlaceAndValues() {
		return paramPlaceAndValues;
	}
	
	public static enum AscOrDesc {
		ASC("asc"), DESC("desc");
		
		private String value;
		private AscOrDesc(String value) {
			this.value = value;
		}
		public String getValue() {
			return value;
		}
	}
	
	public static enum AndOr {
		AND("and"), OR("or");

		private String value;
		private AndOr(String value){
			this.value = value;
		}
		public String getValue() {
			return value;
		}
	}
	
	@Override
	public String toString() {
		return conditions.append(orderby.toString()).toString();
	}
}	